package com.pocketdigi.plib.core;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;

import com.pocketdigi.plib.R;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;



/**
 * Page管理器,必须是单Activity
 * PageManager在整个Activity生命周期中只能实例化一次,在Activity的onDestory中销毁
 * 销毁后不允许再调任何方法
 * Created by fhp on 14-9-2.
 */
public class PageManager {

    private static PageManager instance;
    private static FragmentManager fragmentManager;
    PageShowListener pageShowListener;
    int containerId=0;
    private PageManager() {
        fragmentManager = PFragmentActivity.getInstance().getSupportFragmentManager();
    }

    /**
     * 创建新实例，只能且必须在Activity的onCreate方法里调用
     * @return
     */
    public static void newInstance(int containerId)
    {
        if (instance == null)
            instance = new PageManager();
        instance.containerId=containerId;
    }
    /**
     * 返回单例PageManager，如果Activity已经销毁，返回null
     * @return
     */
    public static PageManager getInstance() {
        return instance;
    }
    /**
     * 显示页面,
     * 如果栈里有同页面，从栈里找，没有就new
     *
     * @param pageClass RFragment类
     */
    public void showPage(Class<? extends PFragment> pageClass){
        showPage(pageClass, 0, null);
    }
    /**
     * 显示页面,
     * 如果栈里有同页面，从栈里找，没有就new
     *
     * @param pageClass RFragment类
     * @param args      在栈里没有该页面实例时，会调用setArguments传给Fragment,如果有实例，
     *                  会调用onResult，Fragment需要覆盖该方法实现相关操作
     */
    public void showPage(Class<? extends PFragment> pageClass, Bundle args) {
        showPage(pageClass, 0, args);
    }
    /**
     * 显示页面,
     * 如果栈里有同页面，从栈里找，没有就new
     *
     * @param pageClass  RFragment类
     * @param args       在栈里没有该页面实例时，会调用setArguments传给Fragment,如果有实例，
     *                   会调用onResult，Fragment需要覆盖该方法实现相关操作
     * @param requestCode 标记参数来源用
     */
    public void showPage(Class<? extends PFragment> pageClass, int requestCode, Bundle args) {
        List<Fragment> fragmentList = fragmentManager.getFragments();
        boolean inStack = false;
        //如果在历史栈中，弹出
        if(fragmentList!=null) {
            for (Fragment fragment : fragmentList) {
                if (fragment instanceof PFragment) {
                    PFragment sFragment = (PFragment) fragment;
                    if (sFragment.getClass() == pageClass) {
                        try {
                            PLog.d(this, "在历史栈中，弹出");
                            inStack = true;
                            fragmentManager.popBackStack(pageClass.getSimpleName(), 0);
                            sFragment.onResult(requestCode, args);
                            if(pageShowListener!=null)
                                pageShowListener.onPageShow(sFragment);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        break;
                    }
                }
            }
        }
        if (!inStack) {
            //如果不在栈中
            try {
                PLog.d(this, "不在历史栈中，new");
                PFragment fragment = pageClass.newInstance();
                if (args != null)
                    fragment.setArguments(args);
                showNewPage(fragment);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 显示Dialog,必须有一个context参数的构造方法
     * @param dialogClass
     */
    public PDialog showDialog(Class<? extends PDialog> dialogClass){
        return showDialog(dialogClass,null);
    }

    /**
     * 带参数显示Dialog,必须有一个context参数的构造方法
     * @param dialogClass
     * @param args
     */
    @TargetApi(Build.VERSION_CODES.KITKAT)
    public PDialog showDialog(Class<? extends PDialog> dialogClass,Bundle args){
        try {
            Class<?>[] argTypes = {Context.class}; //指明所要调用的构造方法的形参
            Constructor<?> constructor = dialogClass.getConstructor(argTypes);//获取指定参数的构造方法
            PDialog dialog = (PDialog) constructor.newInstance(PFragmentActivity.getInstance());
            if(args!=null) {
                dialog.setArgs(args);
            }
            dialog.show();
            return dialog;
        } catch (InstantiationException | InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;

    }

    private void showNewPage(PFragment sFragment) {
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.setCustomAnimations(R.anim.fragment_fade_in, R.anim.fragment_fade_out, R.anim.fragment_fade_in, R.anim.fragment_fade_out);
        transaction.replace(containerId, sFragment, sFragment.getClass().getSimpleName());
        transaction.addToBackStack(sFragment.getClass().getSimpleName());
        transaction.commitAllowingStateLoss();
        if(pageShowListener!=null)
            pageShowListener.onPageShow(sFragment);
    }


    /**
     * 返回上一个page
     *
     * @return
     */
    public boolean back() {
        if (fragmentManager.getBackStackEntryCount() > 1) {
            List<Fragment> fragments = fragmentManager.getFragments();
            int fragmentCount=0;
            for(Fragment fragment:fragments) {
                if(fragment!=null)
                    fragmentCount++;
            }
            PFragment previousFragment = (PFragment)fragments.get(fragmentCount - 2);
            if(previousFragment==null) {
                PLog.d(this, "previousFragment==null");
            }
            if(pageShowListener!=null)
                pageShowListener.onPageShow(previousFragment);
            fragmentManager.popBackStack();
        }
        return false;
    }

    /**
     * 返回到上一个Fragment,并带参数
     * @param requestCode
     * @param args
     * @return
     */
    public boolean back(int requestCode, Bundle args) {
        if (fragmentManager.getBackStackEntryCount() > 0) {
            List<Fragment> fragments = fragmentManager.getFragments();
            int fragmentCount=0;
            for(Fragment fragment:fragments) {
                if(fragment!=null)
                    fragmentCount++;
            }
            PFragment previousFragment = (PFragment)fragments.get(fragmentCount - 2);
            showPage(previousFragment.getClass(),requestCode,args);
        }
        return false;
    }

    /**
     * 当前是否在第一页
     * @return
     */
    public boolean inFirstPage()
    {
        return fragmentManager.getBackStackEntryCount()==1;
    }

    /**
     * 返回到顶
     *
     * @return
     */
    public boolean backToTop() {
        if (fragmentManager.getBackStackEntryCount() > 0)  {
            try {
                fragmentManager.popBackStackImmediate(0, FragmentManager.POP_BACK_STACK_INCLUSIVE);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return true;
        }
        return false;
    }

    /**
     * 在Activity的onDestory方法里调用
     */
    public void destory() {
        pageShowListener=null;
        instance = null;

    }

    public void setPageShowListener(PageShowListener pageShowListener) {
        this.pageShowListener = pageShowListener;
    }

    /**
     * page显示调用
     */
    public interface PageShowListener {
        void onPageShow(PFragment sFragment);
    }

}